package com.wujunshen.chess;

import com.github.bhlangonijr.chesslib.Board;
import com.github.bhlangonijr.chesslib.PieceType;
import com.github.bhlangonijr.chesslib.Side;
import java.util.*;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class StartPosition {
  public static final Map<PieceType, Float> PIECE_VALUE = new EnumMap<>(PieceType.class);
  public static final Map<Side, Map<PieceType, List<Float>>> SQUARE_VALUE =
      new EnumMap<>(Side.class);

  public static Side initSide;

  static {
    initPieceValue();
    initSquareValue();
  }

  private Board board = new Board();

  private static void initPieceValue() {
    PIECE_VALUE.put(PieceType.PAWN, 10.0f);
    PIECE_VALUE.put(PieceType.KNIGHT, 30.0f);
    PIECE_VALUE.put(PieceType.BISHOP, 30.0f);
    PIECE_VALUE.put(PieceType.ROOK, 50.0f);
    PIECE_VALUE.put(PieceType.QUEEN, 100.0f);
    PIECE_VALUE.put(PieceType.KING, 900.0f);
  }

  private static void initSquareValue() {
    Map<PieceType, List<Float>> blackSquareValue = initBlackSquareValue();
    Map<PieceType, List<Float>> whiteSquareValue = initWhiteSquareValue(blackSquareValue);

    SQUARE_VALUE.put(Side.BLACK, Collections.unmodifiableMap(blackSquareValue));
    SQUARE_VALUE.put(Side.WHITE, Collections.unmodifiableMap(whiteSquareValue));
  }

  private static Map<PieceType, List<Float>> initBlackSquareValue() {
    Map<PieceType, List<Float>> blackSquareValue = new EnumMap<>(PieceType.class);

    // 初始化黑方棋子局面价值
    blackSquareValue.put(
        PieceType.PAWN,
        Arrays.asList(
            0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 5.0F, 5.0F, 5.0F, 5.0F, 5.0F, 5.0F,
            5.0F, 5.0F, 1.0F, 1.0F, 2.0F, 3.0F, 3.0F, 2.0F, 1.0F, 1.0F, 0.5F, 0.5F, 1.0F, 2.5F,
            2.5F, 1.0F, 0.5F, 0.5F, 0.0F, 0.0F, 0.0F, 2.0F, 2.0F, 0.0F, 0.0F, 0.0F, 0.5F, -0.5F,
            -1.0F, 0.0F, 0.0F, -1.0F, -0.5F, 0.5F, 0.5F, 1.0F, 1.0F, -2.0F, -2.0F, 1.0F, 1.0F, 0.5F,
            0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F));
    blackSquareValue.put(
        PieceType.KNIGHT,
        Arrays.asList(
            -5.0F, -4.0F, -3.0F, -3.0F, -3.0F, -3.0F, -4.0F, -5.0F, -4.0F, -2.0F, 0.0F, 0.0F, 0.0F,
            0.0F, -2.0F, -4.0F, -3.0F, 0.0F, 1.0F, 1.5F, 1.5F, 1.0F, 0.0F, -3.0F, -3.0F, 0.5F, 1.5F,
            2.0F, 2.0F, 1.5F, 0.5F, -3.0F, -3.0F, 0.0F, 1.5F, 2.0F, 2.0F, 1.5F, 0.0F, -3.0F, -3.0F,
            0.5F, 1.0F, 1.5F, 1.5F, 1.0F, 0.5F, -3.0F, -4.0F, -2.0F, 0.0F, 0.5F, 0.5F, 0.0F, -2.0F,
            -4.0F, -5.0F, -4.0F, -3.0F, -3.0F, -3.0F, -3.0F, -4.0F, -5.0F));
    blackSquareValue.put(
        PieceType.BISHOP,
        Arrays.asList(
            -2.0F, -1.0F, -1.0F, -1.0F, -1.0F, -1.0F, -1.0F, -2.0F, -1.0F, 0.0F, 0.0F, 0.0F, 0.0F,
            0.0F, 0.0F, -1.0F, -1.0F, 0.0F, 0.5F, 1.0F, 1.0F, 0.5F, 0.0F, -1.0F, -1.0F, 0.5F, 0.5F,
            1.0F, 1.0F, 0.5F, 0.5F, -1.0F, -1.0F, 0.0F, 1.0F, 1.0F, 1.0F, 1.0F, 0.0F, -1.0F, -1.0F,
            1.0F, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F, -1.0F, -1.0F, 0.5F, 0.0F, 0.0F, 0.0F, 0.0F, 0.5F,
            -1.0F, -2.0F, -1.0F, -1.0F, -1.0F, -1.0F, -1.0F, -1.0F, -2.0F));
    blackSquareValue.put(
        PieceType.ROOK,
        Arrays.asList(
            0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.5F, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F,
            1.0F, 0.5F, -0.5F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, -0.5F, -0.5F, 0.0F, 0.0F, 0.0F,
            0.0F, 0.0F, 0.0F, -0.5F, -0.5F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, -0.5F, -0.5F, 0.0F,
            0.0F, 0.0F, 0.0F, 0.0F, 0.0F, -0.5F, -0.5F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, -0.5F,
            0.0F, 0.0F, 0.0F, 0.5F, 0.5F, 0.0F, 0.0F, 0.0F));
    blackSquareValue.put(
        PieceType.QUEEN,
        Arrays.asList(
            -2.0F, -1.0F, -1.0F, -0.5F, -0.5F, -1.0F, -1.0F, -2.0F, -1.0F, 0.0F, 0.0F, 0.0F, 0.0F,
            0.0F, 0.0F, -1.0F, -1.0F, 0.0F, 0.5F, 0.5F, 0.5F, 0.5F, 0.0F, -1.0F, -0.5F, 0.0F, 0.5F,
            0.5F, 0.5F, 0.5F, 0.0F, -0.5F, 0.0F, 0.0F, 0.5F, 0.5F, 0.5F, 0.5F, 0.0F, -0.5F, -1.0F,
            0.5F, 0.5F, 0.5F, 0.5F, 0.5F, 0.0F, -1.0F, -1.0F, 0.0F, 0.5F, 0.0F, 0.0F, 0.0F, 0.0F,
            -1.0F, -2.0F, -1.0F, -1.0F, -0.5F, -0.5F, -1.0F, -1.0F, -2.0F));
    blackSquareValue.put(
        PieceType.KING,
        Arrays.asList(
            -3.0F, -4.0F, -4.0F, -5.0F, -5.0F, -4.0F, -4.0F, -3.0F, -3.0F, -4.0F, -4.0F, -5.0F,
            -5.0F, -4.0F, -4.0F, -3.0F, -3.0F, -4.0F, -4.0F, -5.0F, -5.0F, -4.0F, -4.0F, -3.0F,
            -3.0F, -4.0F, -4.0F, -5.0F, -5.0F, -4.0F, -4.0F, -3.0F, -2.0F, -3.0F, -3.0F, -4.0F,
            -4.0F, -3.0F, -3.0F, -2.0F, -1.0F, -2.0F, -2.0F, -2.0F, -2.0F, -2.0F, -2.0F, -1.0F,
            2.0F, 2.0F, 0.0F, 0.0F, 0.0F, 0.0F, 2.0F, 2.0F, 2.0F, 3.0F, 1.0F, 0.0F, 0.0F, 1.0F,
            3.0F, 2.0F));

    return blackSquareValue;
  }

  private static Map<PieceType, List<Float>> initWhiteSquareValue(
      Map<PieceType, List<Float>> blackSquareValue) {
    Map<PieceType, List<Float>> whiteSquareValue = new EnumMap<>(PieceType.class);

    for (Map.Entry<PieceType, List<Float>> entry : blackSquareValue.entrySet()) {
      PieceType pieceType = entry.getKey();
      List<Float> blackValue = entry.getValue();
      List<Float> whiteValue = new ArrayList<>(blackValue);
      Collections.reverse(whiteValue);
      whiteSquareValue.put(pieceType, whiteValue);
    }

    return whiteSquareValue;
  }

  public void load(String fen) {
    board.loadFromFen(fen);
    initSide = board.getSideToMove();
  }
}
